package com.silverbox.waimai.dubboApi.payMotion;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.silverbox.core.annotation.DataSource;
import com.silverbox.core.util.HttpUtil;
import com.silverbox.core.util.Utils;
import com.silverbox.shopper.dubboApi.alipay.AlipayServiceApi;
import com.silverbox.shopper.entity.PayModel;
import com.silverbox.sweeporder.common.PayMotionConstants;
import com.silverbox.sweeporder.common.util.Arith;
import com.silverbox.sweeporder.common.util.RandomUtil;
import com.silverbox.sweeporder.controller.thread.CommonThread;
import com.silverbox.sweeporder.service.alipay.impl.SweepAlipayServiceImpl;
import com.silverbox.waimai.entity.OrderPayDetail;
import com.silverbox.waimai.entity.Waimai;
import com.silverbox.waimai.entity.extend.WaimaiExtend;
import com.silverbox.waimai.mapper.OrderPayDetailMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Optional;

/**
 * <pre>
 * 功    能:
 * 涉及版本:
 * 创 建 者: YangYangjun
 * 日    期: 2020-06-08 14:26
 * </pre>
 */
@Service
@DataSource(name = DataSource.DATASOURCE_B)
public class PayMotionApiImpl implements PayMotionApi {

    private static Logger logger = LoggerFactory.getLogger(SweepAlipayServiceImpl.class);

    @Autowired
    private OrderPayDetailMapper orderPayDetailMapper;
    @Value("${memberConsumePointsUrl}")
    private String memberConsumePointsUrl;
    @Value("${marketing.url}")
    private String marketingUrl;

    @Override
    public void saveOrderPayDetail(OrderPayDetail opd) {
        orderPayDetailMapper.insertSelective(opd);
    }

    @Override
    public void updateOrderPayDetail(OrderPayDetail opd) {
        logger.info("opd == "+opd);
        orderPayDetailMapper.updateByPrimaryKeySelective(opd);
    }

    @Override
    public OrderPayDetail getOrderPayDetailByOrderNumAndPayModel(String orderNum, Integer payModel) {
        return orderPayDetailMapper.getOrderPayDetailByOrderNumAndPayModel(orderNum,payModel);
    }

    /*
     *<pre>
     * 说    明: 执行积分消费
     * 涉及版本:
     * 创 建 者: YangYangjun
     * 日    期: 2020-06-09 16:14
     *</pre>
     **/
    @Override
    public OrderPayDetail executeConsumePoints(Waimai waimai, OrderPayDetail orderPayDetail) {
        if(orderPayDetail != null && orderPayDetail.getTotalPrices() != null && orderPayDetail.getTotalPrices() > 0){
            //执行抵扣消费
            //执行查询会员可使用积分
            JSONObject requestParams = new JSONObject(5);
            requestParams.put("shop_id",waimai.getShopperId());
            requestParams.put("store_id",waimai.getShopId());
            requestParams.put("user_uid",waimai.getUid());
            requestParams.put("total_amount",orderPayDetail.getTotalPrices());
            requestParams.put("title",waimai.getShopName() + " 积分消费");//子门店名称+积分消费
            requestParams.put("order_num",waimai.getOrderNum());
            logger.info("executeConsumePoints,request="+ requestParams.toJSONString());
            String scoreConsumeUrl = memberConsumePointsUrl+"/memberUserScore/scoreConsume";
            logger.info("scoreConsumeUrl="+scoreConsumeUrl);
            String scoreConsumeResponse = HttpUtil.buildJsonRequest(scoreConsumeUrl, requestParams.toJSONString(), 60000, 60000, "UTF-8");
            logger.info("executeConsumePoints,response="+ scoreConsumeResponse);

            JSONObject scoreConsumeJsonBase = JSONObject.parseObject(scoreConsumeResponse);
            if("10000".equals(scoreConsumeJsonBase.getString("code"))){
                orderPayDetail.setPayStatus(PayMotionConstants.PayDetailPayStatus.PAID.getValue());
                orderPayDetail.setModifyTime(new Date());
                orderPayDetail.setPayTime(new Date());
                updateOrderPayDetail(orderPayDetail);
            }else {
                return null;
            }
        }
        return orderPayDetail;
    }


    /*
     *<pre>
     * 说    明: 存储支付明细
     * 涉及版本:
     * 创 建 者: YangYangjun
     * 日    期: 2020-06-08 16:05
     *</pre>
     **/
    @Override
    public void saveOrderPayDetails(Waimai waimai){
        OrderPayDetail opd = getOrderPayDetailByOrderNumAndPayModel(waimai.getOrderNum(), waimai.getPayModel());
        opd = Optional.ofNullable(opd).orElse(new OrderPayDetail());
        opd.setStoreId(waimai.getShopId());
        opd.setShopId(waimai.getShopperId());
        opd.setOrderNum(waimai.getOrderNum());
        opd.setPayOrderNum(waimai.getPayOrderNum());
        opd.setPayModel(waimai.getPayModel());
        opd.setTotalFee(waimai.getTotalFee());
        opd.setTotalPay(waimai.getTotalPay());
        opd.setPayCode(waimai.getPayCode());
        opd.setSubject(waimai.getShopName()+" 消费");
        opd.setThirdPromotionFee(waimai.getThirdPromotionFee());
        opd.setMachineId(waimai.getMachineId());
        opd.setPayTime(waimai.getPayTime());
        opd.setPayplatformPromotionFee(waimai.getPayplatformPromotionFee());
        opd.setTotalPrices(waimai.getTotalPrice());
        opd.setTradeNo(waimai.getTradeNo());
//        opd.setPayStatus(PayMotionConstants.PayDetailPayStatus.UNPAID.getValue());//0：未支付，1：已支付，-1已退款，-2现金支出
        Integer payStatus = new Integer(4).equals(waimai.getPayStatus()) ? -1 : waimai.getPayStatus();
        opd.setPayStatus(payStatus);
        opd.setPayType(PayMotionConstants.PayDetailPayType.ONLINE.getValue());//0:线上支付 1:线下支付
        opd.setIsSystemPay(PayMotionConstants.PayDetailIsSystemPay.SYSTEM.getValue());//支付方式类型 0：商家自定义 1：系统支持
        opd.setOrderDate(waimai.getCreateTime());
        opd.setCreateTime(new Date());
        opd.setQuantity(Optional.ofNullable(opd.getQuantity()).orElse(0));
        if(Utils.isEmpty(opd.getId())){
            saveOrderPayDetail(opd);
        }else {
            updateOrderPayDetail(opd);
        }
    }

    /*
     *<pre>
     * 说    明: 会员选择使用积分抵扣支付返回抵扣后价格
     * 涉及版本:
     * 创 建 者: YangYangjun
     * 日    期: 2020-06-09 16:14
     *</pre>
     **/
    @Override
    public Double consumePointsInit(Waimai waimai, Integer isConsumePoints){
        if(!new Integer(1).equals(isConsumePoints)){
            return waimai.getTotalPrice();
        }
        //执行查询会员积分可抵扣金额
        Double deductibleAmount = getMemberPointsDeductibleAmount(waimai);
        Double totalPrice = waimai.getTotalPrice();
        logger.info("totalPrice = "+totalPrice);
        if(deductibleAmount == null){
            return totalPrice;
        }
        //积分总共可抵扣金额
        //抵扣积分所抵扣金额金额 => 100-100=0:100 10-100=-90:10 100-10=90:10
        double consumePointsAmount = Arith.sub(totalPrice,deductibleAmount) >=0 ? deductibleAmount : totalPrice;
        //积分抵扣向下取整
        consumePointsAmount = Math.floor(consumePointsAmount);
        if(consumePointsAmount == 0D){
            return waimai.getTotalPrice();
        }
        logger.info("consumePointsAmount = " + consumePointsAmount);
        double totalPriceAfterPoints = Arith.sub(totalPrice, consumePointsAmount);
        totalPriceAfterPoints = totalPriceAfterPoints >= 0 ? totalPriceAfterPoints : 0;
        logger.info("consumePointsTotalPrice = "+totalPriceAfterPoints);
        //存储支付明细
        OrderPayDetail opd = new OrderPayDetail();
        opd.setStoreId(waimai.getShopId());
        opd.setShopId(waimai.getShopperId());
        opd.setOrderNum(waimai.getOrderNum());
        String payOrderNum = waimai.getOrderNum()+ RandomUtil.getRandomNum(3);
        opd.setPayOrderNum(payOrderNum);
        opd.setPayModel(PayMotionConstants.OrderPayModel.MEMBER_CONSUME_POINTS.getValue());
        opd.setTotalFee(consumePointsAmount);
        opd.setTotalPay(consumePointsAmount);
        opd.setSubject(waimai.getShopName()+" 消费");
//        opd.setThirdPromotionFee(waimai.getThirdPromotionFee());
        opd.setThirdPromotionFee(0D);
        opd.setMachineId(waimai.getMachineId());
        opd.setPayTime(waimai.getPayTime());
//        opd.setPayplatformPromotionFee(waimai.getPayplatformPromotionFee());
        opd.setPayplatformPromotionFee(0D);
        opd.setTotalPrices(consumePointsAmount);
        opd.setTradeNo(waimai.getTradeNo());
//        opd.setPayStatus(PayMotionConstants.PayDetailPayStatus.UNPAID.getValue());//0：未支付，1：已支付，-1已退款，-2现金支出
        Integer payStatus = new Integer(4).equals(waimai.getPayStatus()) ? -1 : waimai.getPayStatus();
        opd.setPayStatus(payStatus);
        opd.setPayType(PayMotionConstants.PayDetailPayType.ONLINE.getValue());//0:线上支付 1:线下支付
        opd.setIsSystemPay(PayMotionConstants.PayDetailIsSystemPay.SYSTEM.getValue());//支付方式类型 0：商家自定义 1：系统支持
        opd.setOrderDate(waimai.getCreateTime());
        //是否已存在支付明细
        OrderPayDetail orderPayDetail = getOrderPayDetailByOrderNumAndPayModel(waimai.getOrderNum(), PayMotionConstants.OrderPayModel.MEMBER_CONSUME_POINTS.getValue());
        logger.info("orderPayDetail = "+opd.getTotalPrices());
        if(orderPayDetail == null){
            opd.setCreateTime(new Date());
            saveOrderPayDetail(opd);
        }else{
            logger.info("orderPayDetail = " + orderPayDetail);
            opd.setId(orderPayDetail.getId());
            opd.setModifyTime(new Date());
            updateOrderPayDetail(opd);
        }
        return totalPriceAfterPoints;
    }

    /*
     *<pre>
     * 说    明: 查询积抵扣金额
     * 涉及版本:
     * 创 建 者: YangYangjun
     * 日    期: 2020-06-28 16:35
     *</pre>
     **/
    private Double getMemberPointsDeductibleAmount(Waimai waimai){
        JSONObject queryMemberDeductibleScoreJson = queryMemberDeductibleScore(waimai.getShopperId(), waimai.getShopId(),waimai.getUid());
        if(Utils.isEmpty(queryMemberDeductibleScoreJson)){
            return null;
        }
        String deductible_amount = queryMemberDeductibleScoreJson.getString("deductible_amount");
        if(deductible_amount == null){
            return null;
        }
        return Math.floor(Double.parseDouble(deductible_amount));
    }

    //查询会员可使用积分(封装给前端使用)
    @Override
    public JSONObject getMemberDeductibleScore(Integer shopId,Integer storeId,String uid){
        JSONObject queryMemberDeductibleScoreJson = queryMemberDeductibleScore(shopId, storeId,uid);
        if(Utils.isEmpty(queryMemberDeductibleScoreJson)){
            return null;
        }
        return queryMemberDeductibleScoreJson;
    }

    //执行查询会员可使用积分
    private JSONObject queryMemberDeductibleScore(Integer shopId,Integer storeId,String uid){
        //执行查询会员可使用积分
        JSONObject requestParams = new JSONObject(3);
        requestParams.put("shopper_id",shopId);
        requestParams.put("user_uid",uid);
        requestParams.put("store_id",storeId);
        String memberDeductibleScoreUrl = memberConsumePointsUrl+"/memberUserScore/queryMemberDeductibleScore";
        logger.info("consumePointsInit,request="+requestParams.toJSONString());
        String memberDeductibleScoreResponse = HttpUtil.buildJsonRequest(memberDeductibleScoreUrl, requestParams.toJSONString(), 60000, 60000, "UTF-8");
        logger.info("consumePointsInit,response="+memberDeductibleScoreResponse);
        if(memberDeductibleScoreResponse == null){
            return null;
        }
        JSONObject memberDeductibleScoreJsonBase = JSONObject.parseObject(memberDeductibleScoreResponse);
        if(!"10000".equals(memberDeductibleScoreJsonBase.getString("code"))){
            return null;
        }
        JSONObject memberDeductibleScoreJson = memberDeductibleScoreJsonBase.getJSONObject("data");
        if(memberDeductibleScoreJson == null){
            return null;
        }
        return memberDeductibleScoreJson;
    }

    /*
     *<pre>
     * 说    明: 执行积分消费退款
     * 涉及版本:
     * 创 建 者: YangYangjun
     * 日    期: 2020-06-10 10:55
     *</pre>
     **/
    @Override
    public void executeRefundPoints(Waimai waimai) {
        OrderPayDetail orderPayDetail = getOrderPayDetailByOrderNumAndPayModel(waimai.getOrderNum(),PayMotionConstants.OrderPayModel.MEMBER_CONSUME_POINTS.getValue());
        if(orderPayDetail == null || orderPayDetail.getTotalPrices() == null || orderPayDetail.getTotalPrices() > 0){
            logger.info("积分退款失败，数据状态不可用="+orderPayDetail);
            return;
        }
        logger.info("进行积分退款,orderPayDetail,orderNum="+orderPayDetail.getOrderNum()+",payStatus="+orderPayDetail.getPayStatus());
        if(!PayMotionConstants.PayDetailPayStatus.PAID.getValue().equals(orderPayDetail.getPayStatus())){
            logger.info("积分退款失败，支付状态不可用="+orderPayDetail);
            return;
        }
        //查询可退积分
        int refundablePoints = this.getRefundablePointsByOrder(waimai);
        if(refundablePoints <= 0){
            return;
        }
        //执行积分退款
        boolean refundFlag = this.executeRefundPoints(waimai, refundablePoints);
        if(!refundFlag){
            return;
        }
        //更新支付明细
        orderPayDetail.setModifyTime(new Date());
        orderPayDetail.setPayStatus(PayMotionConstants.PayDetailPayStatus.REFUNDED.getValue());
        this.updateOrderPayDetail(orderPayDetail);
    }

    /*
     *<pre>
     * 说    明: 查询会员可退积分
     * 涉及版本:
     * 创 建 者: YangYangjun
     * 日    期: 2020-06-24 16:40
     *</pre>
     **/
    private int getRefundablePointsByOrder(Waimai waimai){
        JSONObject requestParams = new JSONObject(4);
        requestParams.put("order_num",waimai.getOrderNum());
        requestParams.put("shop_id",waimai.getShopperId());
        requestParams.put("store_id",waimai.getShopId());
        requestParams.put("user_uid",waimai.getUid());
        String queryRefundPointsUrl = memberConsumePointsUrl+"/memberUserScore/scoreRefund";
        logger.info("queryRefundPoints,request="+requestParams.toJSONString());
        String queryRefundPointsResponse = HttpUtil.buildJsonRequest(queryRefundPointsUrl, requestParams.toJSONString(), 60000, 60000, "UTF-8");
        logger.info("queryRefundPoints,response="+queryRefundPointsResponse);
        if(Utils.isEmpty(queryRefundPointsResponse)){
            return 0;
        }
        JSONObject queryRefundPointsJson = JSONObject.parseObject(queryRefundPointsResponse);
        String queryRefundPoints = queryRefundPointsJson.getString("code");
        if(!"10000".equals(queryRefundPoints)){
            return 0;
        }
        JSONObject data = queryRefundPointsJson.getJSONObject("data");
        if(Utils.isEmpty(data)){
            return 0;
        }
        String refundable_score = data.getString("refundable_score");
        String canRefundPointsStr = Optional.ofNullable(refundable_score).orElse("0");
        return Integer.parseInt(canRefundPointsStr);
    }

    /*
     *<pre>
     * 说    明: 执行积分退款
     * 涉及版本:
     * 创 建 者: YangYangjun
     * 日    期: 2020-06-24 16:49
     *</pre>
     **/
    private boolean executeRefundPoints(Waimai waimai,Integer refundablePoints){
        JSONObject requestParams = new JSONObject(6);
        requestParams.put("order_num",waimai.getOrderNum());
        requestParams.put("shop_id",waimai.getShopperId());
        requestParams.put("store_id",waimai.getShopId());
        requestParams.put("user_uid",waimai.getUid());
        requestParams.put("refund_score",refundablePoints);
        requestParams.put("title",waimai.getShopName() + " 积分退款");//子门店名称+积分消费
        String refundPointsUrl = memberConsumePointsUrl+"/memberUserScore/scoreRefund";

        logger.info("executeRefundPoints,request="+requestParams.toJSONString());
        String refundPointsResponse = HttpUtil.buildJsonRequest(refundPointsUrl, requestParams.toJSONString(), 60000, 60000, "UTF-8");
        logger.info("executeRefundPoints,response="+refundPointsResponse);
        if(Utils.isEmpty(refundPointsResponse)){
            return false;
        }
        JSONObject refundPointsJson = JSONObject.parseObject(refundPointsResponse);
        String code = refundPointsJson.getString("code");
        if(!"10000".equals(code)){
            return false;
        }
        logger.info("退款成功");
        return true;
    }

    /*
     *<pre>
     * 说    明: 优惠券反核销
     * 涉及版本:
     * 创 建 者: YangYangjun
     * 日    期: 2020-05-13 19:43
     *</pre>
     **/
    @Override
    public void cancelVerifyVoucherList(Waimai waimai) {
        if(!Utils.isEmpty(waimai.getPromotionPrice())){
            JSONObject paramsJson = new JSONObject(3);
            paramsJson.put("order_num",waimai.getOrderNum());
            paramsJson.put("out_request_no",waimai.getOrderNum());
            paramsJson.put("shopper_id",waimai.getShopperId());
            paramsJson.put("store_id",waimai.getShopId());
            paramsJson.put("user_uid",waimai.getUid());
            JSONArray paramJsonArray = new JSONArray();
            paramJsonArray.add(paramsJson);
            logger.info("paramJsonArray="+paramJsonArray.toJSONString());
            CommonThread.execute(waimai.getOrderNum(),marketingUrl+"/silverbox/campaign/cancelVerifyVoucherList",paramJsonArray.toJSONString());
        }
    }

    /*
     *<pre>
     * 说    明: 优惠券核销
     * 涉及版本:
     * 创 建 者: YangYangjun
     * 日    期: 2020-06-12 21:34
     *</pre>
     **/
    @Override
    public void executeVouchersVerify(Waimai waimai) {
        String uuid_json = waimai.getExtendParams();
        if(!Utils.isEmpty(uuid_json)){
            JSONObject uuidJson = JSONObject.parseObject(uuid_json);
            if(!uuidJson.containsKey("uuidArray")){
                return;
            }
            JSONArray jsonArr = new JSONArray();
            JSONObject paramJson = new JSONObject(4);
            paramJson.put("order_num",waimai.getOrderNum());
            paramJson.put("out_request_no",waimai.getOrderNum());
            paramJson.put("shopper_id",waimai.getShopperId());
            paramJson.put("store_id",waimai.getShopId());
            paramJson.put("uid",waimai.getUid());
            JSONArray uuidArray = JSONArray.parseArray(uuidJson.getString("uuidArray"));
            paramJson.put("voucher_id",uuidArray.get(0));
            jsonArr.add(paramJson);
            logger.info("核销优惠订单请求参数:"+jsonArr.get(0).toString());
            CommonThread.execute(waimai.getOrderNum(),marketingUrl + "/promotion/saveVerifiedOrderNumRecord",jsonArr.toJSONString());

        }
     }

    /*
     *<pre>
     * 说    明: 验证订单是否由积分抵扣完所有金额
     * 涉及版本:
     * 创 建 者: YangYangjun
     * 日    期: 2020-06-24 16:29
     *</pre>
     **/
    @Override
    public boolean checkOrderFreeByPoints(Waimai waimai){
        OrderPayDetail orderPayDetails = this.getOrderPayDetailByOrderNumAndPayModel(waimai.getOrderNum(), PayMotionConstants.OrderPayModel.MEMBER_CONSUME_POINTS.getValue());
        if(Utils.isEmpty(orderPayDetails)){
            return false;
        }
        Double orderPayDetailTotalPrices = orderPayDetails.getTotalPrices();
        Double orderTotalPrice = waimai.getTotalPrice();
        return new BigDecimal(orderPayDetailTotalPrices).compareTo(new BigDecimal(orderTotalPrice)) == 0;
    }

    /*
     *<pre>
     * 说    明: 获取订单的消费支付类型（结合混合支付）
     * 涉及版本:
     * 创 建 者: YangYangjun
     * 日    期: 2020-06-28 15:22
     *</pre>
     **/
    @Override
    public Integer getPayModelByWaimai(Waimai waimai) {
        if(waimai.getTotalPrice() == 0D){
            //20200627 0元支付payModel 存现金支付
            return PayMotionConstants.OrderPayModel.CASH.getValue();
        }
        //20200628 目前扫码点餐只有积分混合
        OrderPayDetail orderPayDetails = this.getOrderPayDetailByOrderNumAndPayModel(waimai.getOrderNum(), PayMotionConstants.OrderPayModel.MEMBER_CONSUME_POINTS.getValue());
        if(orderPayDetails == null){
            return waimai.getPayModel();
        }
        //如果积分抵扣完成则为积分完成支付
        Double orderPayDetailTotalPrices = orderPayDetails.getTotalPrices();
        Double orderTotalPrice = waimai.getTotalPrice();
        if(new BigDecimal(orderPayDetailTotalPrices).compareTo(new BigDecimal(orderTotalPrice)) == 0){
            return PayMotionConstants.OrderPayModel.MEMBER_CONSUME_POINTS.getValue();
        }else {
            return PayMotionConstants.OrderPayModel.MIXED.getValue();
        }
    }

    @Override
    public List<OrderPayDetail> getOrderPayDetailByOrderNumOutPayModel(String orderNum, Integer payModel) {
       return orderPayDetailMapper.getOrderPayDetailByOrderNumOutPayModel(orderNum,payModel);
    }

    /*
     *<pre>
     * 说    明: 校验用户积分抵扣是否符合当前订单
     * 涉及版本:
     * 创 建 者: YangYangjun
     * 日    期: 2020-06-28 16:23
     *</pre>
     **/
    @Override
    public boolean checkOrderPointsEnoughBeforePay(Waimai waimai) {
        //选择可使用积分抵扣金额
        Double memberPointsDeductibleAmount = getMemberPointsDeductibleAmount(waimai);
        if(memberPointsDeductibleAmount != null){
            //积分消费支付明细
            OrderPayDetail orderPayDetail = getOrderPayDetailByOrderNumAndPayModel(waimai.getOrderNum(), PayMotionConstants.OrderPayModel.MEMBER_CONSUME_POINTS.getValue());
            Double pointsTotalPrice = orderPayDetail.getTotalPrices();
            //如果支付的时候可使用积分不足则更新积分支付记录
            return new BigDecimal(memberPointsDeductibleAmount).compareTo(new BigDecimal(pointsTotalPrice)) >= 0;
        }
        return false;
    }

}
